package com.tegistuff.webos.run;

import com.intellij.execution.ExecutionException;
import com.intellij.execution.Executor;
import com.intellij.execution.configurations.ModuleBasedConfiguration;
import com.intellij.execution.configurations.RunConfigurationModule;
import com.intellij.execution.configurations.RunProfileState;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.DefaultJDOMExternalizer;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.tegistuff.webos.AppComponent;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.json.JSONObject;

import java.util.Collection;
import java.util.List;

/**
 * WebOSRunConfiguration.java
 *
 * Copyright (C) 2011-2012 Timo Tegtmeier.
 * Copyright (C) 2011 Janni Kovacs.
 * All rights reserved.
 */
public class WebOSRunConfiguration extends ModuleBasedConfiguration {

	private RunTarget target = RunTarget.EMULATOR;
	private VirtualFile appFolder = null;
    private VirtualFile pkgFolder = null;
    private VirtualFile srvFolder = null;
    private VirtualFile accFolder = null;

	public boolean UseV1Format = false;
    public boolean UseSeparateOutputFolders = true;
    public boolean FollowLogs = true;
    public int V8DebugPort = 5858;

	public WebOSRunConfiguration(Project project, WebOSConfigurationFactory factory) {
		super(project.getName(), new RunConfigurationModule(project), factory);
	}

	public RunTarget getTarget() {
		return target;
	}

	public void setTarget(RunTarget target) {
		this.target = target;
	}

	@Nullable
	public VirtualFile getAppFolder() {
		return appFolder;
	}

	public void setAppFolder(VirtualFile appFolder) {
		this.appFolder = appFolder;
	}
    
    @Nullable
    public VirtualFile getPkgFolder() {
        return pkgFolder;
    }
    
    public void setPkgFolder(VirtualFile pkgFolder) {
        this.pkgFolder = pkgFolder; 
    }
    
    @Nullable
    public VirtualFile getSrvFolder() {
        return srvFolder;
    }
    
    public void setSrvFolder(VirtualFile srvFolder) {
        this.srvFolder = srvFolder;
    }
    
    @Nullable
    public VirtualFile getAccFolder() {
        return accFolder;
    }
    
    public void setAccFolder(VirtualFile accFolder) {
        this.accFolder = accFolder;
    }

    @Nullable
    public String getOutputFolder() {
        if(!UseSeparateOutputFolders)
            return null;
        try {
            return getProject().getBaseDir().getPath() + "/bin/" + getName();
        } catch(NullPointerException e) {
            return null;
        }
    }

	public List<VirtualFile> getValidAppFolders() {
		return AppComponent.getWebOSAppFoldersInProject(getProject());
	}
    
    public List<VirtualFile> getValidPackageFolders() {
        return AppComponent.getWebOSPackageFoldersInProject(getProject());
    }
    
    public List<VirtualFile> getValidServiceFolders() {
        return AppComponent.getWebOSServiceFoldersInProject(getProject());
    }
    
    public List<VirtualFile> getValidAccountsFolders() {
        return AppComponent.getWebOSAccountsFoldersInProject(getProject());
    }

	@Override
	public Collection<Module> getValidModules() {
		return getAllModules();
	}

	@Override
	protected ModuleBasedConfiguration createInstance() {
		return new WebOSRunConfiguration(getProject(), (WebOSConfigurationFactory) getFactory());
	}

	public WebOSRunConfigurationEditor getConfigurationEditor() {
		return new WebOSRunConfigurationEditor();
	}

	public RunProfileState getState(@NotNull Executor executor, @NotNull ExecutionEnvironment executionEnvironment) throws ExecutionException {
		return new WebOSRunningState(executor, executionEnvironment);
	}
    
    public String getAppId() {
        if(this.getAppFolder() == null)
            return null;
        try {
            VirtualFile appInfoFile = LocalFileSystem.getInstance().findFileByPath(this.getAppFolder().getPath() + "/appinfo.json");
            byte[] appInfoContent = appInfoFile.contentsToByteArray();
            JSONObject appInfo = new JSONObject(new String(appInfoContent, appInfoFile.getCharset()));
            return appInfo.getString("id");
        } catch(Exception e) {
            return null;
        }
    }
    
    private VirtualFile readFileSetting(Element element, String entry) {
        String path = element.getChildText(entry);
        if (path != null)
            return LocalFileSystem.getInstance().findFileByPath(path);
        return null;
    }

	@Override
	public void readExternal(Element element) throws InvalidDataException {
		super.readExternal(element);
		DefaultJDOMExternalizer.readExternal(this, element);

        appFolder = readFileSetting(element, "directory");
        pkgFolder = readFileSetting(element, "package");
        srvFolder = readFileSetting(element, "service");
        accFolder = readFileSetting(element, "accounts");

		String target = element.getChildText("target");
		if (target != null)
			this.target = RunTarget.valueOf(target);
	}

    private void writeFileSetting(Element element, String entry, VirtualFile file) {
        if (file != null)
            element.addContent(new Element(entry).setText(file.getPath()));
    }

	@Override
	public void writeExternal(Element element) throws WriteExternalException {
		super.writeExternal(element);
		DefaultJDOMExternalizer.writeExternal(this, element);

        writeFileSetting(element, "directory", appFolder);
        writeFileSetting(element, "package", pkgFolder);
        writeFileSetting(element, "service", srvFolder);
        writeFileSetting(element, "accounts", accFolder);

		element.addContent(new Element("target").setText(target.name()));
	}

	@Override
	public String suggestedName() {
		if (appFolder != null) {
			return appFolder.getName();
		}
		return super.suggestedName();
	}
}
